package com.scfire.security
import grails.transaction.Transactional;

import org.apache.log4j.Logger
/*import org.codehaus.groovy.grails.plugins.springsecurity.GormUserDetailsService
import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils*/

import grails.plugin.springsecurity.userdetails.GormUserDetailsService
import grails.plugin.springsecurity.userdetails.GrailsUser
import grails.plugin.springsecurity.SpringSecurityUtils

import org.springframework.dao.DataAccessException
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.GrantedAuthorityImpl
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UsernameNotFoundException

class PrepopulateUserDetailsService extends GormUserDetailsService {
	Logger logger = Logger.getLogger(getClass())
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
		return loadUserByUsername(username, true)
	}
	@Override
	public UserDetails loadUserByUsername(String username, boolean loadRoles)
	throws UsernameNotFoundException, DataAccessException {
		//table of member
		Member.withNewSession {
			session->
			def member = Member.findByUsername(username)
			if(!member){
				//create a new user
				member = new Member(username: username, enabled: true, password: 'password',accountExpired:false,accountLocked:false,passwordExpired:false)
				member.save(flush: true)
			}
			//table of authority
			def authority=Authority.findByAuthority("ROLE_USER")
			if(!authority){
				authority = new Authority(authority: "ROLE_USER")
				authority.save(flush: true)
			}
			//table of memberAuthority
			def memberAuthority = MemberAuthority.findByMember(member)
			if(!memberAuthority){
				MemberAuthority.create member, authority, true
			}
//			else if(!userAuth.authority){
//				userAuth.setAuthority(roleType)
//			}
		}
		def conf = SpringSecurityUtils.securityConfig
		String userClassName = conf.userLookup.userDomainClassName
		def dc = grailsApplication.getDomainClass(userClassName)
		if (!dc) {
			throw new RuntimeException("The specified user domain class '$userClassName' is not a domain class")
		}
		Class<?> User = dc.clazz
		
		User.withNewSession { session ->
			def user = User.findWhere((conf.userLookup.usernamePropertyName): username)
			if (!user) {
				log.warn "User not found: $username"
				throw new UsernameNotFoundException('User not found', username)
			}

			Collection<GrantedAuthority> authorities = loadAuthorities(user, username, loadRoles)
			createUserDetails user, authorities
		}

		// Load user details from database
		 
	}
	
	protected Collection<GrantedAuthority> loadAuthorities(user, String username, boolean loadRoles) {
		if (!loadRoles) {
			return []
		}

		def conf = SpringSecurityUtils.securityConfig

		String authoritiesPropertyName = conf.userLookup.authoritiesPropertyName
		String authorityPropertyName = conf.authority.nameField

		Collection<?> userAuthorities = user."$authoritiesPropertyName"
		def authorities = userAuthorities.collect { new GrantedAuthorityImpl(it."$authorityPropertyName") }
		authorities ?: NO_ROLES
	}

	protected UserDetails createUserDetails(user, Collection<GrantedAuthority> authorities) {

		def conf = SpringSecurityUtils.securityConfig

		String usernamePropertyName = conf.userLookup.usernamePropertyName
		String passwordPropertyName = conf.userLookup.passwordPropertyName
		String enabledPropertyName = conf.userLookup.enabledPropertyName
		String accountExpiredPropertyName = conf.userLookup.accountExpiredPropertyName
		String accountLockedPropertyName = conf.userLookup.accountLockedPropertyName
		String passwordExpiredPropertyName = conf.userLookup.passwordExpiredPropertyName

		String username = user."$usernamePropertyName"
		String password = user."$passwordPropertyName"
		boolean enabled = enabledPropertyName ? user."$enabledPropertyName" : true
		boolean accountExpired = accountExpiredPropertyName ? user."$accountExpiredPropertyName" : false
		boolean accountLocked = accountLockedPropertyName ? user."$accountLockedPropertyName" : false
		boolean passwordExpired = passwordExpiredPropertyName ? user."$passwordExpiredPropertyName" : false

		new GrailsUser(username, password, enabled, !accountExpired, !passwordExpired,
				!accountLocked, authorities, user.id)
	}
}
